import { getUuid } from "@/utils/common.methods";
import { SessionInfo, KeyValue, RoleEnum, SiderMenuEnum } from "./@types";
import { Message } from "@arco-design/web-vue";
import { chatDB } from "@/db/chat";
import { AssetInfo } from "./asset";
import { SyncActionEnum, synchronousService } from "@/services/synchronous.service";

export type ChatFileMenuInfo = {
  uid: string;
  label: string;
  assets?: AssetInfo[];
  modeluid: string;
  type: SiderMenuEnum;
  sessions?: SessionInfo[];
  childrens?: ChatFileMenuInfo[];
};

export type ChatFileInfo = {
  currKey?: string;
  menus?: ChatFileMenuInfo[];
};

/** 文档分析支持类型 */
export const accept = '.pdf,.docx,.doc,.pptx,.xlsx,.xls,.csv,.md,.txt,.pub,.py,.js,.html,.ts,.c,.cs,.cpp,.go'

export class ChatFileModel {
  public LOCAL_STORAGE_KEY = "chat-file";
  private _data = <ChatFileInfo>{};
  public _models: KeyValue[] = [
    {
      key: "poe",
      value: "POE",
    },
    {
      key: "gpt4-128k",
      value: "Gpt4-128k",
    },
  ];

  constructor() {}

  public async setData(): Promise<void> {
    let dataStr = (await chatDB.getStr(this.LOCAL_STORAGE_KEY))?.value ;
    this._data = dataStr ? JSON.parse(dataStr) : {};
  }

  /** 左侧目录 */
  public async menus(): Promise<ChatFileMenuInfo[]> {
    if (!this._data?.currKey) {
      await this.setData();
    }
    return this._data?.menus || [];
  }

  public async add(type: SiderMenuEnum, parent?: string): Promise<void> {
    const label = (type === SiderMenuEnum.Group ? "合集" : "会话") + getUuid(5);
    const uid = getUuid();
    const item: ChatFileMenuInfo = { uid, label, type, modeluid: this._models[0].key };
    if (parent) {
      this._data?.menus?.map((val) => {
        if (val.uid === parent) {
          val.childrens = (val.childrens || []).concat(item);
        }
        return val;
      });
    } else {
      this._data = {
        currKey: uid,
        menus: (this._data?.menus || []).concat(item),
      };
    }
    synchronousService.session(this.LOCAL_STORAGE_KEY, SyncActionEnum.Add, item, parent);
    await this.setLocalStorage("add");
  }

  public async edit(uid: string, label: string): Promise<void> {
    let item = {} as ChatFileMenuInfo;
    let parent = undefined;
    this._data.menus?.forEach((menu) => {
      if (menu.uid === uid) {
        menu.label = label;
        item = menu;
      }
      menu.childrens?.forEach((child) => {
        if (child.uid === uid) child.label = label;
      });
    });
    synchronousService.session(this.LOCAL_STORAGE_KEY, SyncActionEnum.Update, item, parent);
    await this.setLocalStorage("edit");
  }

  public async update(menus: ChatFileMenuInfo[]) {
    this._data.menus = menus;
    await this.setLocalStorage("update");
  }

  public async remove(uid: string): Promise<void> {
    this._data.menus = this._data.menus?.filter((val) => {
      val.childrens = val.childrens?.filter((child) => child.uid !== uid);
      return val.uid !== uid;
    });
    this._data.currKey = this._data.menus[0]?.uid || "";
    synchronousService.session(this.LOCAL_STORAGE_KEY, SyncActionEnum.Delete, { uid } as ChatFileMenuInfo);
    await this.setLocalStorage("remove");
  }

  public async setCurrKey(uid: string): Promise<void> {
    this._data.currKey = uid;
    await this.setLocalStorage("setCurrKey");
  }

  public get currKey(): string {
    return this._data?.currKey;
  }

  public get currMenu(): ChatFileMenuInfo {
    if (!this._data?.menus?.length) return;
    const key = this.currKey;
    if (this._data?.menus) {
      for (const item of this._data?.menus) {
        if (item.uid === key) {
          return item;
        } else {
          if (item?.childrens) {
            for (const child of item?.childrens) {
              if (child.uid === key) return child;
            }
          }
        }
      }
    }

    return null;
  }

  public async updatedFile(uid: string, assets: AssetInfo[]) {
    let item = {} as ChatFileMenuInfo;
    let parent = undefined;
    for (const menu of this._data.menus!) {
      if (menu.uid === uid) {
        menu.assets = assets;
        item = menu;
      }
      if (menu?.childrens) {
        for (const child of menu?.childrens) {
          if (child.uid === uid) {
            child.assets = assets;
            item = child;
            parent = menu.uid;
          }
        }
      }
    }
    synchronousService.session(this.LOCAL_STORAGE_KEY, SyncActionEnum.Update, item, parent);
    await this.setLocalStorage("updatedFile");
  }

  /**
   * 创建会话
   * @param role
   * @param richtext
   * @param quote
   * @returns 会话 uid
   */
  public async addMenuAnswer(role: RoleEnum, richtext: string, quote?: string): Promise<string> {
    const uid = getUuid();
    const key = this._data.currKey;
    const session: SessionInfo = { uid, role, timestamp: Date.now(), richtext, quote };
    for (const item of this._data.menus) {
      if (item.uid === key) {
        if (!item.sessions?.length) {
          this.edit(item.uid, richtext?.slice(0, 10));
        }
        item.sessions = (item.sessions || []).concat(session);
      }
      if (item?.childrens) {
        for (const child of item?.childrens) {
          if (child.uid === key) {
            if (!child.sessions?.length) {
              this.edit(child.uid, richtext?.slice(0, 10));
            }
            child.sessions = (child.sessions || []).concat(session);
          }
        }
      }
    }
    synchronousService.message(SyncActionEnum.Add, key, session);
    await this.setLocalStorage("addMenuAnswer");
    return uid;
  }

  public async removeMenuAnswer(uid: string, isnotice: boolean = true) {
    console.log(this._data.menus, uid);
    for (const item of this._data.menus) {
      if (item.uid === this._data.currKey) {
        item.sessions = item.sessions?.filter((val) => val.uid !== uid);
      }
      if (item?.childrens) {
        for (const child of item?.childrens) {
          if (child.uid === this._data.currKey) {
            child.sessions = child.sessions?.filter((val) => val.uid !== uid);
          }
        }
      }
    }
    if (isnotice) Message.success("删除成功");
    synchronousService.message(SyncActionEnum.Delete, this._data.currKey, { uid } as SessionInfo);
    await this.setLocalStorage("removeMenuAnswer");
  }

  /** 清空 */
  public async clear(): Promise<void> {
    this._data = {};
    synchronousService.clearSession(this.LOCAL_STORAGE_KEY);
    await this.setLocalStorage("clear");
  }

  private async setLocalStorage(source: string): Promise<void> {
    console.log("setLocalStoragesetloca >>> source :", source, this._data);
    await chatDB.set(this.LOCAL_STORAGE_KEY, JSON.stringify(this._data));
    // localStorage.setItem(this.LOCAL_STORAGE_KEY, JSON.stringify(this._data));
  }
}
